{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# sklearn-porter\n",
    "\n",
    "Transpile trained scikit-learn estimators to C, Java, JavaScript and others.\n",
    "\n",
    "Repository: [https://github.com/nok/sklearn-porter](https://github.com/nok/sklearn-porter)\n",
    "\n",
    "## Basics\n",
    "\n",
    "**Step 1**: Load data and train a dummy classifier:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,\n",
       "                       max_features=None, max_leaf_nodes=None,\n",
       "                       min_impurity_decrease=0.0, min_impurity_split=None,\n",
       "                       min_samples_leaf=1, min_samples_split=2,\n",
       "                       min_weight_fraction_leaf=0.0, presort=False,\n",
       "                       random_state=None, splitter='best')"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.datasets import load_iris\n",
    "from sklearn.tree import DecisionTreeClassifier\n",
    "\n",
    "X, y = load_iris(return_X_y=True)\n",
    "clf = DecisionTreeClassifier()\n",
    "clf.fit(X, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Step 2**: Port or transpile an estimator:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/*\n",
      "This file is generated by https://github.com/nok/sklearn-porter/\n",
      "\n",
      "Estimator:\n",
      "    DecisionTreeClassifier\n",
      "    https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html\n",
      "\n",
      "Environment:\n",
      "    scikit-learn v0.21.0\n",
      "    sklearn-porter v1.0.0\n",
      "\n",
      "Usage:\n",
      "    1. Execute a prediction:\n",
      "        $ node DecisionTreeClassifier.js feature_1 ... feature_4\n",
      "*/\n",
      "var DecisionTreeClassifier = function(lefts, rights, thresholds, indices, classes) {\n",
      "\n",
      "    this.lefts = lefts;\n",
      "    this.rights = rights;\n",
      "    this.thresholds = thresholds;\n",
      "    this.indices = indices;\n",
      "    this.classes = classes;\n",
      "\n",
      "    var _findMax = function(nums) {\n",
      "        var i = 0, l = nums.length, idx = 0;\n",
      "        for (; i < l; i++) {\n",
      "            idx = nums[i] > nums[idx] ? i : idx;\n",
      "        }\n",
      "        return idx;\n",
      "    };\n",
      "\n",
      "    var _normVals = function(nums) {\n",
      "        var i, l = nums.length,\n",
      "            result = [],\n",
      "            sum = 0.;\n",
      "        for (i = 0; i < l; i++) {\n",
      "            sum += nums[i];\n",
      "        }\n",
      "        if(sum === 0) {\n",
      "            for (i = 0; i < l; i++) {\n",
      "                result[i] = 1.0 / l;\n",
      "            }\n",
      "        } else {\n",
      "            for (i = 0; i < l; i++) {\n",
      "                result[i] = nums[i] / sum;\n",
      "            }\n",
      "        }\n",
      "        return result;\n",
      "    };\n",
      "\n",
      "    this._compute = function(features, node, post) {\n",
      "        node = (typeof node !== 'undefined') ? node : 0;\n",
      "        if (this.thresholds[node] !== -2) {\n",
      "            if (features[this.indices[node]] <= this.thresholds[node]) {\n",
      "                return this._compute(features, this.lefts[node], post);\n",
      "            } else {\n",
      "                return this._compute(features, this.rights[node], post);\n",
      "            }\n",
      "        }\n",
      "        return post(this.classes[node]);\n",
      "    };\n",
      "\n",
      "    this.predict = function(features, node) {\n",
      "        return this._compute(features, node, _findMax);\n",
      "    };\n",
      "\n",
      "    this.predictProba = function(features, node) {\n",
      "        return this._compute(features, node, _normVals);\n",
      "    };\n",
      "\n",
      "};\n",
      "\n",
      "var main = function () {\n",
      "    if (typeof process !== 'undefined' && typeof process.argv !== 'undefined') {\n",
      "        if (process.argv.length - 2 !== 4) {\n",
      "            var IllegalArgumentException = function(message) {\n",
      "                this.message = message;\n",
      "                this.name = \"IllegalArgumentException\";\n",
      "            }\n",
      "            throw new IllegalArgumentException(\"You have to pass 4 features.\");\n",
      "        }\n",
      "    }\n",
      "\n",
      "    // Features:\n",
      "    var features = process.argv.slice(2);\n",
      "    for (var i = 0; i < features.length; i++) {\n",
      "        features[i] = parseFloat(features[i]);\n",
      "    }\n",
      "\n",
      "    // Model data:\n",
      "    var lefts = [1, -1, 3, 4, 5, -1, -1, 8, -1, 10, -1, -1, 13, 14, -1, -1, -1];\n",
      "    var rights = [2, -1, 12, 7, 6, -1, -1, 9, -1, 11, -1, -1, 16, 15, -1, -1, -1];\n",
      "    var thresholds = [2.449999988079071, -2.0, 1.75, 4.950000047683716, 1.6500000357627869, -2.0, -2.0, 1.550000011920929, -2.0, 5.450000047683716, -2.0, -2.0, 4.8500001430511475, 5.950000047683716, -2.0, -2.0, -2.0];\n",
      "    var indices = [2, -2, 3, 2, 3, -2, -2, 3, -2, 2, -2, -2, 2, 0, -2, -2, -2];\n",
      "    var classes = [[50, 50, 50], [50, 0, 0], [0, 50, 50], [0, 49, 5], [0, 47, 1], [0, 47, 0], [0, 0, 1], [0, 2, 4], [0, 0, 3], [0, 2, 1], [0, 2, 0], [0, 0, 1], [0, 1, 45], [0, 1, 2], [0, 1, 0], [0, 0, 2], [0, 0, 43]];\n",
      "\n",
      "    // Estimator:\n",
      "    var clf = new DecisionTreeClassifier(lefts, rights, thresholds, indices, classes);\n",
      "\n",
      "    // Get class prediction:\n",
      "    var prediction = clf.predict(features);\n",
      "    console.log(\"Predicted class: #\" + prediction);\n",
      "\n",
      "    // Get class probabilities:\n",
      "    var probabilities = clf.predictProba(features);\n",
      "    for (var i = 0; i < probabilities.length; i++) {\n",
      "        console.log(\"Probability of class #\" + i + \" : \" + probabilities[i]);\n",
      "    }\n",
      "}\n",
      "\n",
      "if (require.main === module) {\n",
      "    main();\n",
      "}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from sklearn_porter import port, save, make, test\n",
    "\n",
    "output = port(clf, language='js', template='attached')\n",
    "\n",
    "print(output)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Step 3**: Save the ported estimator:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/tmp/DecisionTreeClassifier.js /tmp/DecisionTreeClassifier.json\n"
     ]
    }
   ],
   "source": [
    "src_path, json_path = save(clf, language='js', template='exported', directory='/tmp')\n",
    "\n",
    "print(src_path, json_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "title": "[shell]"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[37m/*\u001b[39;49;00m\r\n",
      "\u001b[37mThis file is generated by https://github.com/nok/sklearn-porter/\u001b[39;49;00m\r\n",
      "\u001b[37m\u001b[39;49;00m\r\n",
      "\u001b[37mEstimator:\u001b[39;49;00m\r\n",
      "\u001b[37m    DecisionTreeClassifier\u001b[39;49;00m\r\n",
      "\u001b[37m    https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html\u001b[39;49;00m\r\n",
      "\u001b[37m\u001b[39;49;00m\r\n",
      "\u001b[37mEnvironment:\u001b[39;49;00m\r\n",
      "\u001b[37m    scikit-learn v0.21.0\u001b[39;49;00m\r\n",
      "\u001b[37m    sklearn-porter v1.0.0\u001b[39;49;00m\r\n",
      "\u001b[37m\u001b[39;49;00m\r\n",
      "\u001b[37mUsage:\u001b[39;49;00m\r\n",
      "\u001b[37m    1. Execute a prediction:\u001b[39;49;00m\r\n",
      "\u001b[37m        $ node DecisionTreeClassifier.js DecisionTreeClassifier.json feature_1 ... feature_4\u001b[39;49;00m\r\n",
      "\u001b[37m*/\u001b[39;49;00m\r\n",
      "\u001b[34mvar\u001b[39;49;00m fs = require(\u001b[33m'fs'\u001b[39;49;00m);\r\n",
      "\r\n",
      "\r\n",
      "\u001b[34mvar\u001b[39;49;00m DecisionTreeClassifier = \u001b[34mfunction\u001b[39;49;00m(jsonFile) {\r\n",
      "    \u001b[34mthis\u001b[39;49;00m.data = JSON.parse(fs.readFileSync(jsonFile));\r\n",
      "\r\n",
      "    \u001b[34mthis\u001b[39;49;00m.lefts = \u001b[34mthis\u001b[39;49;00m.data.lefts;\r\n",
      "    \u001b[34mthis\u001b[39;49;00m.rights = \u001b[34mthis\u001b[39;49;00m.data.rights;\r\n",
      "    \u001b[34mthis\u001b[39;49;00m.thresholds = \u001b[34mthis\u001b[39;49;00m.data.thresholds;\r\n",
      "    \u001b[34mthis\u001b[39;49;00m.indices = \u001b[34mthis\u001b[39;49;00m.data.indices;\r\n",
      "    \u001b[34mthis\u001b[39;49;00m.classes = \u001b[34mthis\u001b[39;49;00m.data.classes;\r\n",
      "\r\n",
      "    \u001b[34mvar\u001b[39;49;00m _findMax = \u001b[34mfunction\u001b[39;49;00m(nums) {\r\n",
      "        \u001b[34mvar\u001b[39;49;00m i = \u001b[34m0\u001b[39;49;00m, l = nums.length, idx = \u001b[34m0\u001b[39;49;00m;\r\n",
      "        \u001b[34mfor\u001b[39;49;00m (; i < l; i++) {\r\n",
      "            idx = nums[i] > nums[idx] ? i : idx;\r\n",
      "        }\r\n",
      "        \u001b[34mreturn\u001b[39;49;00m idx;\r\n",
      "    };\r\n",
      "\r\n",
      "    \u001b[34mvar\u001b[39;49;00m _normVals = \u001b[34mfunction\u001b[39;49;00m(nums) {\r\n",
      "        \u001b[34mvar\u001b[39;49;00m i, l = nums.length,\r\n",
      "            result = [],\r\n",
      "            sum = \u001b[34m0.\u001b[39;49;00m;\r\n",
      "        \u001b[34mfor\u001b[39;49;00m (i = \u001b[34m0\u001b[39;49;00m; i < l; i++) {\r\n",
      "            sum += nums[i];\r\n",
      "        }\r\n",
      "        \u001b[34mif\u001b[39;49;00m(sum === \u001b[34m0\u001b[39;49;00m) {\r\n",
      "            \u001b[34mfor\u001b[39;49;00m (i = \u001b[34m0\u001b[39;49;00m; i < l; i++) {\r\n",
      "                result[i] = \u001b[34m1.0\u001b[39;49;00m / l;\r\n",
      "            }\r\n",
      "        } \u001b[34melse\u001b[39;49;00m {\r\n",
      "            \u001b[34mfor\u001b[39;49;00m (i = \u001b[34m0\u001b[39;49;00m; i < l; i++) {\r\n",
      "                result[i] = nums[i] / sum;\r\n",
      "            }\r\n",
      "        }\r\n",
      "        \u001b[34mreturn\u001b[39;49;00m result;\r\n",
      "    };\r\n",
      "\r\n",
      "    \u001b[34mthis\u001b[39;49;00m._compute = \u001b[34mfunction\u001b[39;49;00m(features, node, post) {\r\n",
      "        node = (\u001b[34mtypeof\u001b[39;49;00m node !== \u001b[33m'undefined'\u001b[39;49;00m) ? node : \u001b[34m0\u001b[39;49;00m;\r\n",
      "        \u001b[34mif\u001b[39;49;00m (\u001b[34mthis\u001b[39;49;00m.thresholds[node] !== -\u001b[34m2\u001b[39;49;00m) {\r\n",
      "            \u001b[34mif\u001b[39;49;00m (features[\u001b[34mthis\u001b[39;49;00m.indices[node]] <= \u001b[34mthis\u001b[39;49;00m.thresholds[node]) {\r\n",
      "                \u001b[34mreturn\u001b[39;49;00m \u001b[34mthis\u001b[39;49;00m._compute(features, \u001b[34mthis\u001b[39;49;00m.lefts[node], post);\r\n",
      "            } \u001b[34melse\u001b[39;49;00m {\r\n",
      "                \u001b[34mreturn\u001b[39;49;00m \u001b[34mthis\u001b[39;49;00m._compute(features, \u001b[34mthis\u001b[39;49;00m.rights[node], post);\r\n",
      "            }\r\n",
      "        }\r\n",
      "        \u001b[34mreturn\u001b[39;49;00m post(\u001b[34mthis\u001b[39;49;00m.classes[node]);\r\n",
      "    };\r\n",
      "\r\n",
      "    \u001b[34mthis\u001b[39;49;00m.predict = \u001b[34mfunction\u001b[39;49;00m(features, node) {\r\n",
      "        \u001b[34mreturn\u001b[39;49;00m \u001b[34mthis\u001b[39;49;00m._compute(features, node, _findMax);\r\n",
      "    };\r\n",
      "\r\n",
      "    \u001b[34mthis\u001b[39;49;00m.predictProba = \u001b[34mfunction\u001b[39;49;00m(features, node) {\r\n",
      "        \u001b[34mreturn\u001b[39;49;00m \u001b[34mthis\u001b[39;49;00m._compute(features, node, _normVals);\r\n",
      "    };\r\n",
      "};\r\n",
      "\r\n",
      "\u001b[34mvar\u001b[39;49;00m main = \u001b[34mfunction\u001b[39;49;00m () {\r\n",
      "    \u001b[37m// Features:\u001b[39;49;00m\r\n",
      "    \u001b[34mvar\u001b[39;49;00m features = process.argv.slice(\u001b[34m3\u001b[39;49;00m);\r\n",
      "    \u001b[34mfor\u001b[39;49;00m (\u001b[34mvar\u001b[39;49;00m i = \u001b[34m0\u001b[39;49;00m; i < features.length; i++) {\r\n",
      "        features[i] = \u001b[36mparseFloat\u001b[39;49;00m(features[i]);\r\n",
      "    }\r\n",
      "\r\n",
      "    \u001b[37m// Model data:\u001b[39;49;00m\r\n",
      "    \u001b[34mvar\u001b[39;49;00m json = process.argv[\u001b[34m2\u001b[39;49;00m];\r\n",
      "\r\n",
      "    \u001b[37m// Estimator:\u001b[39;49;00m\r\n",
      "    \u001b[34mvar\u001b[39;49;00m clf = \u001b[34mnew\u001b[39;49;00m DecisionTreeClassifier(json);\r\n",
      "\r\n",
      "    \u001b[37m// Get class prediction:\u001b[39;49;00m\r\n",
      "    \u001b[34mvar\u001b[39;49;00m prediction = clf.predict(features);\r\n",
      "    console.log(\u001b[33m\"Predicted class: #\"\u001b[39;49;00m + prediction);\r\n",
      "\r\n",
      "    \u001b[37m// Get class probabilities:\u001b[39;49;00m\r\n",
      "    \u001b[34mvar\u001b[39;49;00m probabilities = clf.predictProba(features);\r\n",
      "    \u001b[34mfor\u001b[39;49;00m (\u001b[34mvar\u001b[39;49;00m i = \u001b[34m0\u001b[39;49;00m; i < probabilities.length; i++) {\r\n",
      "        console.log(\u001b[33m\"Probability of class #\"\u001b[39;49;00m + i + \u001b[33m\" : \"\u001b[39;49;00m + probabilities[i]);\r\n",
      "    }\r\n",
      "}\r\n",
      "\r\n",
      "\u001b[34mif\u001b[39;49;00m (require.main === module) {\r\n",
      "    main();\r\n",
      "}\r\n"
     ]
    }
   ],
   "source": [
    "cat /tmp/DecisionTreeClassifier.js | pygmentize -l javascript"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "title": "[shell]"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\u001b[34;01m\"lefts\"\u001b[39;49;00m:[\u001b[34m1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m3\u001b[39;49;00m,\u001b[34m4\u001b[39;49;00m,\u001b[34m5\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m8\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m10\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m13\u001b[39;49;00m,\u001b[34m14\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m],\u001b[34;01m\"rights\"\u001b[39;49;00m:[\u001b[34m2\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m12\u001b[39;49;00m,\u001b[34m7\u001b[39;49;00m,\u001b[34m6\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m9\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m11\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m16\u001b[39;49;00m,\u001b[34m15\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m],\u001b[34;01m\"thresholds\"\u001b[39;49;00m:[\u001b[34m2.449999988079071\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m1.75\u001b[39;49;00m,\u001b[34m4.950000047683716\u001b[39;49;00m,\u001b[34m1.6500000357627869\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m1.550000011920929\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m5.450000047683716\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m4.8500001430511475\u001b[39;49;00m,\u001b[34m5.950000047683716\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m],\u001b[34;01m\"indices\"\u001b[39;49;00m:[\u001b[34m2\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m3\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m,\u001b[34m3\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m3\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m],\u001b[34;01m\"classes\"\u001b[39;49;00m:[[\u001b[34m50\u001b[39;49;00m,\u001b[34m50\u001b[39;49;00m,\u001b[34m50\u001b[39;49;00m],[\u001b[34m50\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m50\u001b[39;49;00m,\u001b[34m50\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m49\u001b[39;49;00m,\u001b[34m5\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m47\u001b[39;49;00m,\u001b[34m1\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m47\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m,\u001b[34m1\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m,\u001b[34m4\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m,\u001b[34m3\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m,\u001b[34m1\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m,\u001b[34m1\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m1\u001b[39;49;00m,\u001b[34m45\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m1\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m1\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m,\u001b[34m43\u001b[39;49;00m]]}\r\n"
     ]
    }
   ],
   "source": [
    "cat /tmp/DecisionTreeClassifier.json | pygmentize -l json"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Step 4**: Make predictions with the ported estimator:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 0 0 0 0 0 0 0 0 0] [[1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]]\n"
     ]
    }
   ],
   "source": [
    "y_classes, y_probas = make(clf, X[:10], language='js', template='exported')\n",
    "\n",
    "print(y_classes, y_probas)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Step 5**: Test always the ported estimator by making an integrity check:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.0\n"
     ]
    }
   ],
   "source": [
    "score = test(clf, X[:10], language='js', template='exported')\n",
    "\n",
    "print(score)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## OOP\n",
    "\n",
    "**Step 1**: Port or transpile an estimator:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/**\n",
      " * This file is generated by https://github.com/nok/sklearn-porter/\n",
      " *\n",
      " * Estimator:\n",
      " *     DecisionTreeClassifier\n",
      " *     https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html\n",
      " *\n",
      " * Environment:\n",
      " *     scikit-learn v0.21.0\n",
      " *     sklearn-porter v1.0.0\n",
      " *\n",
      " * Usage:\n",
      " *     1. Compile the generated source code:\n",
      " *         $ javac DecisionTreeClassifier.java\n",
      " *     2. Execute a prediction:\n",
      " *         $ java DecisionTreeClassifier feature_1 ... feature_4\n",
      " */\n",
      "class DecisionTreeClassifier {\n",
      "\n",
      "    private int[] lefts;\n",
      "    private int[] rights;\n",
      "    private double[] thresholds;\n",
      "    private int[] indices;\n",
      "    private int[][] classes;\n",
      "\n",
      "    public DecisionTreeClassifier(int[] lefts, int[] rights, double[] thresholds, int[] indices, int[][] classes) {\n",
      "        this.lefts = lefts;\n",
      "        this.rights = rights;\n",
      "        this.thresholds = thresholds;\n",
      "        this.indices = indices;\n",
      "        this.classes = classes;\n",
      "    }\n",
      "\n",
      "    private int findMax(int[] nums) {\n",
      "        int i = 0, l = nums.length, idx = 0;\n",
      "        for (i = 0; i < l; i++) {\n",
      "            idx = nums[i] > nums[idx] ? i : idx;\n",
      "        }\n",
      "        return idx;\n",
      "    }\n",
      "\n",
      "    private double[] normVals(int[] nums) {\n",
      "        int i = 0, l = nums.length;\n",
      "        double[] result = new double[l];\n",
      "        double sum = 0.;\n",
      "        for (i = 0; i < l; i++) {\n",
      "            sum += nums[i];\n",
      "        }\n",
      "        if(sum == 0) {\n",
      "            for (i = 0; i < l; i++) {\n",
      "                result[i] = 1.0 / nums.length;\n",
      "            }\n",
      "        } else {\n",
      "            for (i = 0; i < l; i++) {\n",
      "                result[i] = nums[i] / sum;\n",
      "            }\n",
      "        }\n",
      "        return result;\n",
      "    }\n",
      "\n",
      "    private int predict(double[] features, int node) {\n",
      "        if (this.thresholds[node] != -2) {\n",
      "            if (features[this.indices[node]] <= this.thresholds[node]) {\n",
      "                return predict(features, this.lefts[node]);\n",
      "            } else {\n",
      "                return predict(features, this.rights[node]);\n",
      "            }\n",
      "        }\n",
      "        return findMax(this.classes[node]);\n",
      "    }\n",
      "\n",
      "    public int predict(double[] features) {\n",
      "        return this.predict(features, 0);\n",
      "    }\n",
      "\n",
      "    private double[] predictProba(double[] features, int node) {\n",
      "        if (this.thresholds[node] != -2) {\n",
      "            if (features[this.indices[node]] <= this.thresholds[node]) {\n",
      "                return this.predictProba(features, this.lefts[node]);\n",
      "            } else {\n",
      "                return this.predictProba(features, this.rights[node]);\n",
      "            }\n",
      "        }\n",
      "        return normVals(this.classes[node]);\n",
      "    }\n",
      "\n",
      "    public double[] predictProba (double[] features) {\n",
      "        return this.predictProba(features, 0);\n",
      "    }\n",
      "\n",
      "    public static void main(String[] args) {\n",
      "        int nFeatures = 4;\n",
      "        if (args.length != nFeatures) {\n",
      "            throw new IllegalArgumentException(\"You have to pass \" +  String.valueOf(nFeatures) + \" features.\");\n",
      "        }\n",
      "\n",
      "        // Features:\n",
      "        double[] features = new double[args.length];\n",
      "        for (int i = 0, l = args.length; i < l; i++) {\n",
      "            features[i] = Double.parseDouble(args[i]);\n",
      "        }\n",
      "\n",
      "        // Model data:\n",
      "        int[] lefts = {1, -1, 3, 4, 5, -1, -1, 8, -1, 10, -1, -1, 13, 14, -1, -1, -1};\n",
      "        int[] rights = {2, -1, 12, 7, 6, -1, -1, 9, -1, 11, -1, -1, 16, 15, -1, -1, -1};\n",
      "        double[] thresholds = {2.449999988079071, -2.0, 1.75, 4.950000047683716, 1.6500000357627869, -2.0, -2.0, 1.550000011920929, -2.0, 5.450000047683716, -2.0, -2.0, 4.8500001430511475, 5.950000047683716, -2.0, -2.0, -2.0};\n",
      "        int[] indices = {2, -2, 3, 2, 3, -2, -2, 3, -2, 2, -2, -2, 2, 0, -2, -2, -2};\n",
      "        int[][] classes = {{50, 50, 50}, {50, 0, 0}, {0, 50, 50}, {0, 49, 5}, {0, 47, 1}, {0, 47, 0}, {0, 0, 1}, {0, 2, 4}, {0, 0, 3}, {0, 2, 1}, {0, 2, 0}, {0, 0, 1}, {0, 1, 45}, {0, 1, 2}, {0, 1, 0}, {0, 0, 2}, {0, 0, 43}};\n",
      "\n",
      "        // Estimator:\n",
      "        DecisionTreeClassifier clf = new DecisionTreeClassifier(lefts, rights, thresholds, indices, classes);\n",
      "\n",
      "        // Get class prediction:\n",
      "        int prediction = clf.predict(features);\n",
      "        System.out.println(\"Predicted class: #\" + String.valueOf(prediction));\n",
      "\n",
      "        // Get class probabilities:\n",
      "        double[] probabilities = clf.predictProba(features);\n",
      "        for (int i = 0; i < probabilities.length; i++) {\n",
      "            System.out.println(\"Probability of class #\" + i + \" : \" + String.valueOf(probabilities[i]));\n",
      "        }\n",
      "\n",
      "    }\n",
      "}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from sklearn_porter import Estimator\n",
    "\n",
    "est = Estimator(clf, language='java', template='attached')\n",
    "output = est.port()\n",
    "\n",
    "print(output)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Step 2**: Save the ported estimator:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/tmp/DecisionTreeClassifier.java /tmp/DecisionTreeClassifier.json\n"
     ]
    }
   ],
   "source": [
    "est.template = 'exported'\n",
    "src_path, json_path = est.save(directory='/tmp')\n",
    "\n",
    "print(src_path, json_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "title": "[shell]"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[37m/**\u001b[39;49;00m\r\n",
      "\u001b[37m * This file is generated by https://github.com/nok/sklearn-porter/\u001b[39;49;00m\r\n",
      "\u001b[37m *\u001b[39;49;00m\r\n",
      "\u001b[37m * Estimator:\u001b[39;49;00m\r\n",
      "\u001b[37m *     DecisionTreeClassifier\u001b[39;49;00m\r\n",
      "\u001b[37m *     https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html\u001b[39;49;00m\r\n",
      "\u001b[37m *\u001b[39;49;00m\r\n",
      "\u001b[37m * Environment:\u001b[39;49;00m\r\n",
      "\u001b[37m *     scikit-learn v0.21.0\u001b[39;49;00m\r\n",
      "\u001b[37m *     sklearn-porter v1.0.0\u001b[39;49;00m\r\n",
      "\u001b[37m *\u001b[39;49;00m\r\n",
      "\u001b[37m * Usage:\u001b[39;49;00m\r\n",
      "\u001b[37m *     1. Download dependencies:\u001b[39;49;00m\r\n",
      "\u001b[37m *         $ wget --quiet -O gson.jar http://central.maven.org/maven2/com/google/code/gson/gson/2.8.5/gson-2.8.5.jar\u001b[39;49;00m\r\n",
      "\u001b[37m *     2. Compile the generated source code:\u001b[39;49;00m\r\n",
      "\u001b[37m *         $ javac -cp gson.jar DecisionTreeClassifier.java\u001b[39;49;00m\r\n",
      "\u001b[37m *     3. Execute a prediction:\u001b[39;49;00m\r\n",
      "\u001b[37m *         $ java -cp .:gson.jar DecisionTreeClassifier DecisionTreeClassifier.json feature_1 ... feature_4\u001b[39;49;00m\r\n",
      "\u001b[37m */\u001b[39;49;00m\r\n",
      "\u001b[34mimport\u001b[39;49;00m \u001b[04m\u001b[36mcom.google.gson.Gson\u001b[39;49;00m;\r\n",
      "\r\n",
      "\u001b[34mimport\u001b[39;49;00m \u001b[04m\u001b[36mjava.io.File\u001b[39;49;00m;\r\n",
      "\u001b[34mimport\u001b[39;49;00m \u001b[04m\u001b[36mjava.io.FileNotFoundException\u001b[39;49;00m;\r\n",
      "\u001b[34mimport\u001b[39;49;00m \u001b[04m\u001b[36mjava.util.Scanner\u001b[39;49;00m;\r\n",
      "\r\n",
      "\u001b[34mclass\u001b[39;49;00m \u001b[04m\u001b[32mDecisionTreeClassifier\u001b[39;49;00m {\r\n",
      "\r\n",
      "    \u001b[34mprivate\u001b[39;49;00m \u001b[34mclass\u001b[39;49;00m \u001b[04m\u001b[32mTree\u001b[39;49;00m {\r\n",
      "        \u001b[34mprivate\u001b[39;49;00m \u001b[36mint\u001b[39;49;00m[] lefts;\r\n",
      "        \u001b[34mprivate\u001b[39;49;00m \u001b[36mint\u001b[39;49;00m[] rights;\r\n",
      "        \u001b[34mprivate\u001b[39;49;00m \u001b[36mdouble\u001b[39;49;00m[] thresholds;\r\n",
      "        \u001b[34mprivate\u001b[39;49;00m \u001b[36mint\u001b[39;49;00m[] indices;\r\n",
      "        \u001b[34mprivate\u001b[39;49;00m \u001b[36mint\u001b[39;49;00m[][] classes;\r\n",
      "    }\r\n",
      "    \u001b[34mprivate\u001b[39;49;00m Tree tree;\r\n",
      "\r\n",
      "    \u001b[34mpublic\u001b[39;49;00m \u001b[32mDecisionTreeClassifier\u001b[39;49;00m(String file) \u001b[34mthrows\u001b[39;49;00m FileNotFoundException {\r\n",
      "        String jsonStr = \u001b[34mnew\u001b[39;49;00m Scanner(\u001b[34mnew\u001b[39;49;00m File(file)).\u001b[36museDelimiter\u001b[39;49;00m(\u001b[33m\"\\\\Z\"\u001b[39;49;00m).\u001b[36mnext\u001b[39;49;00m();\r\n",
      "        \u001b[34mthis\u001b[39;49;00m.\u001b[36mtree\u001b[39;49;00m = \u001b[34mnew\u001b[39;49;00m Gson().\u001b[36mfromJson\u001b[39;49;00m(jsonStr, Tree.\u001b[36mclass\u001b[39;49;00m);\r\n",
      "    }\r\n",
      "\r\n",
      "    \u001b[34mprivate\u001b[39;49;00m \u001b[36mint\u001b[39;49;00m \u001b[32mfindMax\u001b[39;49;00m(\u001b[36mint\u001b[39;49;00m[] nums) {\r\n",
      "        \u001b[36mint\u001b[39;49;00m idx = \u001b[34m0\u001b[39;49;00m;\r\n",
      "        \u001b[34mfor\u001b[39;49;00m (\u001b[36mint\u001b[39;49;00m i = \u001b[34m0\u001b[39;49;00m; i < nums.\u001b[36mlength\u001b[39;49;00m; i++) {\r\n",
      "            idx = nums[i] > nums[idx] ? i : idx;\r\n",
      "        }\r\n",
      "        \u001b[34mreturn\u001b[39;49;00m idx;\r\n",
      "    }\r\n",
      "\r\n",
      "    \u001b[34mprivate\u001b[39;49;00m \u001b[36mdouble\u001b[39;49;00m[] \u001b[32mnormVals\u001b[39;49;00m(\u001b[36mint\u001b[39;49;00m[] nums) {\r\n",
      "        \u001b[36mint\u001b[39;49;00m i = \u001b[34m0\u001b[39;49;00m, l = nums.\u001b[36mlength\u001b[39;49;00m;\r\n",
      "        \u001b[36mdouble\u001b[39;49;00m[] result = \u001b[34mnew\u001b[39;49;00m \u001b[36mdouble\u001b[39;49;00m[l];\r\n",
      "        \u001b[36mdouble\u001b[39;49;00m sum = \u001b[34m0.\u001b[39;49;00m;\r\n",
      "        \u001b[34mfor\u001b[39;49;00m (i = \u001b[34m0\u001b[39;49;00m; i < l; i++) {\r\n",
      "            sum += nums[i];\r\n",
      "        }\r\n",
      "        \u001b[34mif\u001b[39;49;00m(sum == \u001b[34m0\u001b[39;49;00m) {\r\n",
      "            \u001b[34mfor\u001b[39;49;00m (i = \u001b[34m0\u001b[39;49;00m; i < l; i++) {\r\n",
      "                result[i] = \u001b[34m1.0\u001b[39;49;00m / nums.\u001b[36mlength\u001b[39;49;00m;\r\n",
      "            }\r\n",
      "        } \u001b[34melse\u001b[39;49;00m {\r\n",
      "            \u001b[34mfor\u001b[39;49;00m (i = \u001b[34m0\u001b[39;49;00m; i < l; i++) {\r\n",
      "                result[i] = nums[i] / sum;\r\n",
      "            }\r\n",
      "        }\r\n",
      "        \u001b[34mreturn\u001b[39;49;00m result;\r\n",
      "    }\r\n",
      "\r\n",
      "    \u001b[34mprivate\u001b[39;49;00m \u001b[36mint\u001b[39;49;00m \u001b[32mpredict\u001b[39;49;00m(\u001b[36mdouble\u001b[39;49;00m[] features, \u001b[36mint\u001b[39;49;00m node) {\r\n",
      "        \u001b[34mif\u001b[39;49;00m (\u001b[34mthis\u001b[39;49;00m.\u001b[36mtree\u001b[39;49;00m.\u001b[36mthresholds\u001b[39;49;00m[node] != -\u001b[34m2\u001b[39;49;00m) {\r\n",
      "            \u001b[34mif\u001b[39;49;00m (features[\u001b[34mthis\u001b[39;49;00m.\u001b[36mtree\u001b[39;49;00m.\u001b[36mindices\u001b[39;49;00m[node]] <= \u001b[34mthis\u001b[39;49;00m.\u001b[36mtree\u001b[39;49;00m.\u001b[36mthresholds\u001b[39;49;00m[node]) {\r\n",
      "                \u001b[34mreturn\u001b[39;49;00m predict(features, \u001b[34mthis\u001b[39;49;00m.\u001b[36mtree\u001b[39;49;00m.\u001b[36mlefts\u001b[39;49;00m[node]);\r\n",
      "            } \u001b[34melse\u001b[39;49;00m {\r\n",
      "                \u001b[34mreturn\u001b[39;49;00m predict(features, \u001b[34mthis\u001b[39;49;00m.\u001b[36mtree\u001b[39;49;00m.\u001b[36mrights\u001b[39;49;00m[node]);\r\n",
      "            }\r\n",
      "        }\r\n",
      "        \u001b[34mreturn\u001b[39;49;00m findMax(\u001b[34mthis\u001b[39;49;00m.\u001b[36mtree\u001b[39;49;00m.\u001b[36mclasses\u001b[39;49;00m[node]);\r\n",
      "    }\r\n",
      "\r\n",
      "    \u001b[34mpublic\u001b[39;49;00m \u001b[36mint\u001b[39;49;00m \u001b[32mpredict\u001b[39;49;00m(\u001b[36mdouble\u001b[39;49;00m[] features) {\r\n",
      "        \u001b[34mreturn\u001b[39;49;00m \u001b[34mthis\u001b[39;49;00m.\u001b[36mpredict\u001b[39;49;00m(features, \u001b[34m0\u001b[39;49;00m);\r\n",
      "    }\r\n",
      "\r\n",
      "    \u001b[34mprivate\u001b[39;49;00m \u001b[36mdouble\u001b[39;49;00m[] \u001b[32mpredictProba\u001b[39;49;00m(\u001b[36mdouble\u001b[39;49;00m[] features, \u001b[36mint\u001b[39;49;00m node) {\r\n",
      "        \u001b[34mif\u001b[39;49;00m (\u001b[34mthis\u001b[39;49;00m.\u001b[36mtree\u001b[39;49;00m.\u001b[36mthresholds\u001b[39;49;00m[node] != -\u001b[34m2\u001b[39;49;00m) {\r\n",
      "            \u001b[34mif\u001b[39;49;00m (features[\u001b[34mthis\u001b[39;49;00m.\u001b[36mtree\u001b[39;49;00m.\u001b[36mindices\u001b[39;49;00m[node]] <= \u001b[34mthis\u001b[39;49;00m.\u001b[36mtree\u001b[39;49;00m.\u001b[36mthresholds\u001b[39;49;00m[node]) {\r\n",
      "                \u001b[34mreturn\u001b[39;49;00m predictProba(features, \u001b[34mthis\u001b[39;49;00m.\u001b[36mtree\u001b[39;49;00m.\u001b[36mlefts\u001b[39;49;00m[node]);\r\n",
      "            } \u001b[34melse\u001b[39;49;00m {\r\n",
      "                \u001b[34mreturn\u001b[39;49;00m predictProba(features, \u001b[34mthis\u001b[39;49;00m.\u001b[36mtree\u001b[39;49;00m.\u001b[36mrights\u001b[39;49;00m[node]);\r\n",
      "            }\r\n",
      "        }\r\n",
      "        \u001b[34mreturn\u001b[39;49;00m normVals(\u001b[34mthis\u001b[39;49;00m.\u001b[36mtree\u001b[39;49;00m.\u001b[36mclasses\u001b[39;49;00m[node]);\r\n",
      "    }\r\n",
      "\r\n",
      "    \u001b[34mpublic\u001b[39;49;00m \u001b[36mdouble\u001b[39;49;00m[] \u001b[32mpredictProba\u001b[39;49;00m (\u001b[36mdouble\u001b[39;49;00m[] features) {\r\n",
      "        \u001b[34mreturn\u001b[39;49;00m \u001b[34mthis\u001b[39;49;00m.\u001b[36mpredictProba\u001b[39;49;00m(features, \u001b[34m0\u001b[39;49;00m);\r\n",
      "    }\r\n",
      "\r\n",
      "    \u001b[34mpublic\u001b[39;49;00m \u001b[34mstatic\u001b[39;49;00m \u001b[36mvoid\u001b[39;49;00m \u001b[32mmain\u001b[39;49;00m(String[] args) \u001b[34mthrows\u001b[39;49;00m FileNotFoundException {\r\n",
      "        \u001b[36mint\u001b[39;49;00m nFeatures = \u001b[34m4\u001b[39;49;00m;\r\n",
      "        \u001b[34mif\u001b[39;49;00m (args.\u001b[36mlength\u001b[39;49;00m != (nFeatures + \u001b[34m1\u001b[39;49;00m) || !args[\u001b[34m0\u001b[39;49;00m].\u001b[36mendsWith\u001b[39;49;00m(\u001b[33m\".json\"\u001b[39;49;00m)) {\r\n",
      "            \u001b[34mthrow\u001b[39;49;00m \u001b[34mnew\u001b[39;49;00m IllegalArgumentException(\u001b[33m\"You have to pass the path to the exported model data and \"\u001b[39;49;00m +  String.\u001b[36mvalueOf\u001b[39;49;00m(nFeatures) + \u001b[33m\" features.\"\u001b[39;49;00m);\r\n",
      "        }\r\n",
      "\r\n",
      "        \u001b[37m// Features:\u001b[39;49;00m\r\n",
      "        \u001b[36mdouble\u001b[39;49;00m[] features = \u001b[34mnew\u001b[39;49;00m \u001b[36mdouble\u001b[39;49;00m[args.\u001b[36mlength\u001b[39;49;00m-\u001b[34m1\u001b[39;49;00m];\r\n",
      "        \u001b[34mfor\u001b[39;49;00m (\u001b[36mint\u001b[39;49;00m i = \u001b[34m1\u001b[39;49;00m, l = args.\u001b[36mlength\u001b[39;49;00m; i < l; i++) {\r\n",
      "            features[i - \u001b[34m1\u001b[39;49;00m] = Double.\u001b[36mparseDouble\u001b[39;49;00m(args[i]);\r\n",
      "        }\r\n",
      "\r\n",
      "        \u001b[37m// Model data:\u001b[39;49;00m\r\n",
      "        String modelData = args[\u001b[34m0\u001b[39;49;00m];\r\n",
      "\r\n",
      "        \u001b[37m// Estimator:\u001b[39;49;00m\r\n",
      "        DecisionTreeClassifier clf = \u001b[34mnew\u001b[39;49;00m DecisionTreeClassifier(modelData);\r\n",
      "\r\n",
      "        \u001b[37m// Get class prediction:\u001b[39;49;00m\r\n",
      "        \u001b[36mint\u001b[39;49;00m prediction = clf.\u001b[36mpredict\u001b[39;49;00m(features);\r\n",
      "        System.\u001b[36mout\u001b[39;49;00m.\u001b[36mprintln\u001b[39;49;00m(\u001b[33m\"Predicted class: #\"\u001b[39;49;00m + String.\u001b[36mvalueOf\u001b[39;49;00m(prediction));\r\n",
      "\r\n",
      "        \u001b[37m// Get class probabilities:\u001b[39;49;00m\r\n",
      "        \u001b[36mdouble\u001b[39;49;00m[] probabilities = clf.\u001b[36mpredictProba\u001b[39;49;00m(features);\r\n",
      "        \u001b[34mfor\u001b[39;49;00m (\u001b[36mint\u001b[39;49;00m i = \u001b[34m0\u001b[39;49;00m; i < probabilities.\u001b[36mlength\u001b[39;49;00m; i++) {\r\n",
      "            System.\u001b[36mout\u001b[39;49;00m.\u001b[36mprint\u001b[39;49;00m(String.\u001b[36mvalueOf\u001b[39;49;00m(probabilities[i]));\r\n",
      "            \u001b[34mif\u001b[39;49;00m (i != probabilities.\u001b[36mlength\u001b[39;49;00m - \u001b[34m1\u001b[39;49;00m) {\r\n",
      "                System.\u001b[36mout\u001b[39;49;00m.\u001b[36mprint\u001b[39;49;00m(\u001b[33m\",\"\u001b[39;49;00m);\r\n",
      "            }\r\n",
      "        }\r\n",
      "\r\n",
      "    }\r\n",
      "}\r\n"
     ]
    }
   ],
   "source": [
    "cat /tmp/DecisionTreeClassifier.java | pygmentize -l java"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "title": "[shell]"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\u001b[34;01m\"lefts\"\u001b[39;49;00m:[\u001b[34m1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m3\u001b[39;49;00m,\u001b[34m4\u001b[39;49;00m,\u001b[34m5\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m8\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m10\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m13\u001b[39;49;00m,\u001b[34m14\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m],\u001b[34;01m\"rights\"\u001b[39;49;00m:[\u001b[34m2\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m12\u001b[39;49;00m,\u001b[34m7\u001b[39;49;00m,\u001b[34m6\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m9\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m11\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m16\u001b[39;49;00m,\u001b[34m15\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m,\u001b[34m-1\u001b[39;49;00m],\u001b[34;01m\"thresholds\"\u001b[39;49;00m:[\u001b[34m2.449999988079071\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m1.75\u001b[39;49;00m,\u001b[34m4.950000047683716\u001b[39;49;00m,\u001b[34m1.6500000357627869\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m1.550000011920929\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m5.450000047683716\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m4.8500001430511475\u001b[39;49;00m,\u001b[34m5.950000047683716\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m,\u001b[34m-2.0\u001b[39;49;00m],\u001b[34;01m\"indices\"\u001b[39;49;00m:[\u001b[34m2\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m3\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m,\u001b[34m3\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m3\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m,\u001b[34m-2\u001b[39;49;00m],\u001b[34;01m\"classes\"\u001b[39;49;00m:[[\u001b[34m50\u001b[39;49;00m,\u001b[34m50\u001b[39;49;00m,\u001b[34m50\u001b[39;49;00m],[\u001b[34m50\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m50\u001b[39;49;00m,\u001b[34m50\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m49\u001b[39;49;00m,\u001b[34m5\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m47\u001b[39;49;00m,\u001b[34m1\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m47\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m,\u001b[34m1\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m,\u001b[34m4\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m,\u001b[34m3\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m,\u001b[34m1\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m,\u001b[34m1\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m1\u001b[39;49;00m,\u001b[34m45\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m1\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m1\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m,\u001b[34m2\u001b[39;49;00m],[\u001b[34m0\u001b[39;49;00m,\u001b[34m0\u001b[39;49;00m,\u001b[34m43\u001b[39;49;00m]]}\r\n"
     ]
    }
   ],
   "source": [
    "cat /tmp/DecisionTreeClassifier.json | pygmentize -l json"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Step 3**: Make predictions with the ported estimator:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 0 0 0 0 0 0 0 0 0] [[1. 0. 0.]\n",
      " [1. 0. 0.]\n",
      " [1. 0. 0.]\n",
      " [1. 0. 0.]\n",
      " [1. 0. 0.]\n",
      " [1. 0. 0.]\n",
      " [1. 0. 0.]\n",
      " [1. 0. 0.]\n",
      " [1. 0. 0.]\n",
      " [1. 0. 0.]]\n"
     ]
    }
   ],
   "source": [
    "y_classes, y_probas = est.make(X[:10])\n",
    "\n",
    "print(y_classes, y_probas)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Step 4**: Test always the ported estimator by making an integrity check:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.0\n"
     ]
    }
   ],
   "source": [
    "score = est.test(X[:10])\n",
    "\n",
    "print(score)"
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "title,-all",
   "main_language": "python",
   "notebook_metadata_filter": "-all"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
